#ifndef __PROCESS_POOR_HPP__
#define __PROCESS_POOR_HPP__

#include <iostream>
#include "Channel.hpp"
#include "Task.hpp"
#include <functional>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include<sys/wait.h>

using work_t = std::function<void()>;

enum
{
	Success = 0,
	UsageError,
	PipeError,
	ForkError
};

class ProcessPool
{
public:
	ProcessPool(int n, work_t w) : PipeNum(n), work(w) {}

	int InitProcessPool()
	{
		for (int i = 0; i < PipeNum; i++)
		{
			int pipefd[2] = {0};
			int n = pipe(pipefd);
			if (n < 0)
			{
				return PipeError;
			}

			pid_t pid = fork();
			if (pid < 0)
			{
				return ForkError;
			}

			if (pid == 0)
			{
				// 关闭历史wfd
				//fork复制了子进程指向上面pipe的写端
				std::cout << "child: "<<getpid()<<",close history fd:";
				for (auto &c : channels)
				{
					std::cout << c.wFd() << " ";
					c.Close();
				}
				std::cout << "over" << std::endl;

				::close(pipefd[1]);
				//std::cout << "debug:" << pipefd[0] << std::endl;
				dup2(pipefd[0], 0);
				work();
				sleep(1);
				::exit(0);
			}

			::close(pipefd[0]);
			channels.emplace_back(pipefd[1], pid); // 效率比push_back更高
		}

		return Success;
	}

	void DispatchTask(){
		int who=0;
		int TaskNum=20;
		while(TaskNum--){
			int task=tm.Select();

			Channel &curr=channels[who++];
			who%=channels.size();

			std::cout<<"###########################"<<std::endl;
			std::cout<<"Send "<<task<<" to "<<curr.Name()<<" 任务还剩："<<TaskNum<<std::endl;
			std::cout<<"###########################"<<std::endl;
			curr.Send(task);
			sleep(1);
		}
	}
	
	void CleanProcessPool(){
		for(auto &c:channels){
			c.Close();
			pid_t rid=::waitpid(c.Id(),nullptr,0);
			if(rid>0){
				std::cout<<"child "<<rid<<" wait...success"<<std::endl;
			}
			sleep(1);
		}

		//把父子进程执行pipe的所有写端都关掉才能自动关掉pipe
		// for(auto &c :channels){
		// 	c.Close();
		// }
		// for(auto &c:channels){
		// 	pid_t rid=::waitpid(c.Id(),nullptr,0);
		// 	if(rid>0){
		// 		std::cout<<"child "<<rid<<"wait...success"<<std::endl;
		// 	}
		// }

	}

	~ProcessPool(){}

private:
	std::vector<Channel> channels;
	int PipeNum;
	work_t work;
};

#endif
